#pragma once
#include <memory>
#include <unordered_map>
#include "Epoller.hpp"
#include "connection.hpp"
class Reactor
{
    static const int EpollMax = 1999;

private:
    bool IsExitConnection(std::shared_ptr<Connection> con)
    {
        auto pos = _connetions.find(con->GetFd());
        if (pos == _connetions.end())
            return false;
        else
            return true;
    }
    void PrintConnection()
    {
        std::cout << "当前Reactor正在进行管理的fd List:";
        for (auto &conn : _connetions)
        {
            std::cout << conn.second->GetFd() << " ";
        }
        std::cout << "\r\n";
    }

    int LoopOnce()
    {
        int n = _eptr->EpollWaid(_events, EpollMax, -1);
        return n;
    }
    void Dispatcher(int n)
    {
        // if (n > 0)
        // {
        //     for (int i = 0; i < n; i++)
        //     {
        //         int fd = _events[i].data.fd;
        //         uint32_t revent = _events[i].events;
        //         LOG(LogLevel::DEBUG) << "fd:"<<fd << "有事件就绪";
        //         if (revent & EPOLLIN)
        //         {
        //             LOG(LogLevel::DEBUG) << 1;
        //         }
        //         if (revent & EPOLLOUT)
        //         {
        //             LOG(LogLevel::DEBUG) << 2;
        //         }
        //         if (revent & EPOLLERR)
        //         {
        //             LOG(LogLevel::DEBUG) << 3;
        //         }
        //         if (revent & EPOLLHUP)
        //         {
        //             LOG(LogLevel::DEBUG) << 4;
        //         }
        //         // 处理连接关闭事件
        //         if (revent & EPOLLRDHUP)
        //         {
        //             LOG(LogLevel::DEBUG) << "Connection closed by peer (EPOLLRDHUP), fd: " << fd;
        //         }
        //     }
        // }
        for (int i = 0; i < n; i++)
        {
            int fd = _events[i].data.fd;
            uint32_t revent = _events[i].events;

            // 将我们的epolll wait出错转化为我们的io事件
            // epoll_wait 返回不仅仅代表我们的事件就绪了
            if (revent & EPOLLRDHUP)
            {
                LOG(LogLevel::DEBUG) << "Connection closed by peer (EPOLLRDHUP), fd: " << fd;
                revent |= (EPOLLIN | EPOLLOUT);
            }
            if (revent & EPOLLERR)
            {
                LOG(LogLevel::ERROR) << "Error on connection, fd: " << fd;
                revent |= (EPOLLIN | EPOLLOUT);
            }
            if (revent & EPOLLHUP)
            {
                LOG(LogLevel::DEBUG) << "Connection hung up (EPOLLHUP), fd: " << fd;
                revent |= (EPOLLIN | EPOLLOUT);
            }
            if (revent & EPOLLIN)
            {
                // 读事件就绪
                _connetions[fd]->RECV();
            }
            if (revent & EPOLLOUT)
            {
                // 写事件就绪
                _connetions[fd]->SEND();
            }
        }
    }

public:
    Reactor()
        : _eptr(std::make_unique<Epoller>()), _isrunning(false)
    {
    }
    void Loop()
    {
        _isrunning = true;
        while (_isrunning)
        {
            sleep(1);
            PrintConnection();
            // 阻塞调用 有事件就绪 内核唤醒用户进程
            int n = LoopOnce();
            Dispatcher(n); // 派发事件
        }
    }
    ~Reactor()
    {
    }
    void AddConnection(std::shared_ptr<Connection> value)
    {
        if (IsExitConnection(value))
            return;
        int fd = value->GetFd();
        uint32_t event = value->GetEvent();
        // 设置当前fd的回指指针
        value->SetOwn(this);
        // 加入我们的管理容器中
        _connetions.insert(std::make_pair(fd, value));
        // 下面写在内核中
        _eptr->EpollAdd(fd, event);
    }
    void DelConnection(int fd)
    {

        auto pos = _connetions.find(fd);
        if (pos == _connetions.end())
        {
            return;
        }
        auto tem = _connetions[fd];
        InetAddr *client = tem->GetClient();
        // 从管理容器中删除
        _connetions.erase(fd);
        // 下面从epoll中移除对改fd的关心
        _eptr->EpollDel(fd);

        // 接下来进行文件描述符的关闭
        close(fd);
        if (client)
        {
            LOG(LogLevel::DEBUG) << client->StringAddr() << "离开了";
        }
        else
        {
            LOG(LogLevel::DEBUG)<<"连接套接字出现问题";
        }
    }
    void EnableReadWrite(int _sockfd, bool enableread, bool enablewrite)
    {
        auto pos=_connetions.find(_sockfd);
        if(pos==_connetions.end()) return;
        auto tem=_connetions[_sockfd];
        uint32_t newevent=(EPOLLET|(enableread?EPOLLIN:0)|(enablewrite?EPOLLOUT:0));
        tem->SetEvent(newevent);
        //写再内核中
        _eptr->EpollMod(_sockfd,newevent);
    }   

private:
    std::unique_ptr<Epoller> _eptr; // epoll模型指针
    bool _isrunning;

    // 管理所有的fd 通过基类指针来接受
    std::unordered_map<int, std::shared_ptr<Connection>> _connetions;

    struct epoll_event _events[EpollMax];
};